#include <ntddk.h>

struct MyDataItem
{
	unsigned long Data;
	LIST_ENTRY Link;
};

MyDataItem* 
GetMyDataItem(LIST_ENTRY *pLink);

VOID
DriverUnload(_In_ PDRIVER_OBJECT DriverObject);

EXTERN_C
NTSTATUS
DriverEntry(_In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegisterPath)
{
	DriverObject->DriverUnload = DriverUnload;

	LIST_ENTRY HeadLink;
	InitializeListHead(&HeadLink);

	for (unsigned int i = 0; i < 10; i++) {
		MyDataItem* DataItem = (MyDataItem*)ExAllocatePoolWithTag(PagedPool, sizeof(MyDataItem), 'Ling');
		if (DataItem == nullptr) {
			KdPrint(("ExAllocatePoolWithTag Error\n"));
			return !STATUS_SUCCESS;
		}
		DataItem->Data = i;
		InsertHeadList(&HeadLink, &DataItem->Link);
	}

	for (PLIST_ENTRY Nodel = HeadLink.Flink; Nodel != &HeadLink; Nodel = Nodel->Flink) {
		KdPrint(("%lu\n", GetMyDataItem(Nodel)->Data));
	}

	KdPrint(("===============================================\n"));

	while (IsListEmpty(&HeadLink) == false) {
		PLIST_ENTRY Node = RemoveTailList(&HeadLink);

		MyDataItem* DataItem = GetMyDataItem(Node);
		KdPrint(("Element being deleted: %lu\n", DataItem->Data));

		ExFreePool(DataItem);
	}

	KdPrint(("Driver loaded successfully\n"));

	return STATUS_SUCCESS;
}

VOID
DriverUnload(_In_ PDRIVER_OBJECT DriverObject)
{
	KdPrint(("Driver uninstalled successfully\n"));
}

MyDataItem*
GetMyDataItem(LIST_ENTRY *pLink)
{
	return CONTAINING_RECORD(pLink, MyDataItem, Link);
}